#!/usr/bin/env python

import os
import re
import gzip
import urllib
import urllib2
import StringIO
import BeautifulSoup

class Anidb(object):
    '''Anidb class
    
    @author Julot <andy.julot@gmail.com>
    @since Friday, January 27, 2012. 06:42 PM'''
    
    aid = 0
    
    def __init__(self, aid):
        self.aid = aid
        attrs = {
            'type': 'type',
            'episodecount': 'episodecount',
            'startdate': 'startdate',
            'enddate': 'enddate',
            'picture': 'picture',
            'description': 'description',
            'titles': {'element': 'title', 'class': '_Title'}
        }
        
        for attr in attrs:
            if isinstance(attrs[attr], basestring):
                setattr(self, attrs[attr], '?')
            else:
                setattr(self, attr, [])
        
        path = os.path.join('xml', '%s.xml' % aid)
        if not os.path.lexists(path): return
        
        soup = BeautifulSoup.BeautifulStoneSoup(open(path))
        
        # TODO:
        # If description is not available, find will get any level description.
        # even though we only need top level description.
        # We cannot better than this for a while because the xml from AniDb
        # contains </anime> in the lower level which messed up the BeautifulSoup
        for attr in attrs:
            if isinstance(attrs[attr], basestring):
                element = soup.find(attrs[attr])
                if element:
                    content = element.contents[0].replace('`', "'")
                    setattr(self, attr, content.replace('&amp;', '&'))
            else:
                elements = soup.find(attr)
                for element in elements.findAll(attrs[attr]['element']):
                    obj = globals()[attrs[attr]['class']](element)
                    objs = getattr(self, attr)
                    objs.append(obj)
                    setattr(self, attr, objs)
    
    @staticmethod
    def downloadTitles():
        pass
    
    @property
    def humanDescription(self):
        pattern = r"http:[-/\.a-zA-Z0-9]* \[([^\]]+)\]"
        return re.sub(pattern, r"\1", self.description)
    
    @property
    def hasPicture(self):
        path = os.path.join('image', self.picture)
        return os.path.lexists(path)
    
    @property
    def pictureUrl(self):
        return 'http://img7.anidb.net/pics/anime/%s' % self.picture
    
    @property
    def picturePath(self):
        return os.path.join('image', self.picture)
    
    @property
    def xmlPath(self):
        return os.path.join('xml', '%s.xml' % self.aid)
    
    @property
    def hasXml(self):
        return os.path.lexists(self.xmlPath)
    
    @property
    def xmlUrl(self):
        url  = 'http://api.anidb.net:9001/httpapi?request=anime&'
        url += 'client=xbmcscrap&clientver=1&protover=1&aid=%s'
        return url % self.aid
    
    _romanjiTitle = None
    
    @property
    def romanjiTitle(self):
        if not self._romanjiTitle:
            for title in self.titles:
                language = title.LANGUAGE_X_JAT
                if title.language == language and title.type == title.TYPE_MAIN:
                    self._romanjiTitle = title.value
                    break
        return self._romanjiTitle
    
    _kanjiTitle = None
    
    @property
    def kanjiTitle(self):
        if not self._kanjiTitle:
            for title in self.titles:
                language = title.LANGUAGE_JA
                type = title.TYPE_OFFICIAL
                if title.language == language and title.type == type:
                    self._kanjiTitle = title.value
                    break
        return self._kanjiTitle
    
    @property
    def startYear(self):
        try:
            year = int(self.startdate[0:4])
        except:
            year = 0
        return year
    
    @property
    def startMonth(self):
        try:
            month = int(self.startdate[5:7])
        except:
            month = 0
        return month
    
    @property
    def startDay(self):
        try:
            day = int(self.startdate[8:10])
        except:
            day = 0
        return day
    
    def downloadXml(self):
        request = urllib2.Request(self.xmlUrl)
        request.add_header('Accept-encoding', 'gzip')
        opener = urllib2.build_opener()
        try:
            f = opener.open(request)
            compresseddata = f.read()
        except:
            return False
        compressedstream = StringIO.StringIO(compresseddata)
        gzipper = gzip.GzipFile(fileobj=compressedstream)
        data = gzipper.read()
        xmlfile = open(self.xmlPath, 'w')
        xmlfile.write(data)
        xmlfile.close()
        return True
    
    def downloadImage(self):
        try:
            urllib.urlretrieve(self.pictureUrl, self.picturePath)
        except:
            return False
        return False
    
class _Title(object):
    '''Title class
    
    @author Julot <andy.julot@gmail.com>
    @since Sunday, January 29, 2012. 11:53 AM'''
    
    TYPE_MAIN = 'main'
    TYPE_OFFICIAL = 'official'
    LANGUAGE_X_JAT = 'x-jat'
    LANGUAGE_JA = 'ja'
    
    def __init__(self, element):
        value = element.contents[0].replace('`', "'")
        self.value = value.replace('&amp;', '&').strip()
        self.language = element.get('xml:lang')
        self.type = element.get('type')
    
    @property
    def humanLanguage(self):
        if self.language == 'ja': return 'Japanesse'
        if self.language == 'x-jat': return 'Japanesse'
        if self.language == 'en': return 'English'
        if self.language == 'ru': return 'Russian'
        if self.language == 'de': return 'German'
        if self.language == 'fr': return 'French'
        if self.language == 'it': return 'Italian'
        if self.language == 'sv': return 'Swedish'
        if self.language == 'ca': return 'Catalan'
        if self.language == 'cs': return 'Czech'
        if self.language == 'pl': return 'Polish'
        if self.language == 'es': return 'Spanish'
        if self.language == 'ko': return 'Korean'
        if self.language == 'pt-BR': return 'Brazilian Portuguese'
        else: return self.language
    
    @property
    def humanType(self):
        if self.type == 'main': return 'Main Title'
        if self.type == 'official': return 'Official Title'
        return self.type.capitalize()
